package com.example.basic.snowflake;

import java.time.*;
import java.util.function.Function;

/**
 * 偏移时钟
 * @author fanhang
 */
public interface OffsetClock {
    /**
     * 获取当前偏移时间
     * @return 当前偏移时间
     */
    long get();

    /**
     * 解析真实时间
     * @param offset 偏移时间
     * @return 真实时间
     */
    Instant parse(long offset);



    static OffsetClock millis(LocalDateTime baseTime) {
        return new CachedOffsetClock(baseTime, Duration::toSeconds, offset -> baseTime.plus(Duration.ofMillis(offset)));
    }

    static OffsetClock seconds(LocalDateTime baseTime) {
        return new CachedOffsetClock(baseTime, Duration::toSeconds, baseTime::plusSeconds);
    }

    static OffsetClock minute(LocalDateTime baseTime) {
        Function<Long, LocalDateTime> func = baseTime::plusMinutes;
        return new CachedOffsetClock(baseTime, Duration::toMinutes, baseTime::plusMinutes);
    }

    static OffsetClock hour(LocalDateTime baseTime) {
        return new CachedOffsetClock(baseTime, Duration::toHours, baseTime::plusHours);
    }

    class CachedOffsetClock implements OffsetClock {
        private final LocalDateTime baseTime;
        private final Function<Duration, Long> getFun;
        private final Function<Long, LocalDateTime> parseFunc;

        public CachedOffsetClock(LocalDateTime baseTime, Function<Duration, Long> getFun, Function<Long, LocalDateTime> parseFunc) {
            this.baseTime = baseTime;
            this.getFun = getFun;
            this.parseFunc = parseFunc;
        }

        public long get() {
            return getFun.apply(Duration.between(baseTime, LocalDateTime.now()));
        }

        @Override
        public Instant parse(long offset) {
            return parseFunc.apply(offset).toInstant(ZoneOffset.ofHours(8));
        }
    }
}
